{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Re-creating R. L. Draper's *top spin*\n",
    "\n",
    "By [Allison Parrish](https://www.decontextualize.com/)\n",
    "\n",
    "This notebook shows how to recreate R. L. Draper's concrete poem *top spin*, as reproduced in [How to read a concrete poem](http://www.futureanachronism.com/digitalpaper/HowToReadAConcretePoem.pdf), with Python ranges, `for` loops, and string indexing.\n",
    "\n",
    "The original looks like this:\n",
    "\n",
    "    tops\n",
    "     ops\n",
    "      ps\n",
    "       s\n",
    "       sp\n",
    "       spi\n",
    "       spin\n",
    "       spi\n",
    "       sp\n",
    "       s\n",
    "      ps\n",
    "     ops\n",
    "    tops\n",
    "     ops\n",
    "      ps\n",
    "       s\n",
    "       sp\n",
    "       spi\n",
    "       spin\n",
    "       spi\n",
    "       sp\n",
    "       s\n",
    "      ps\n",
    "     ops\n",
    "    tops\n",
    "    \n",
    "We're going to write some code that achieves this same effect, but can produce an arbitrary number of repetitions and work on any input string.\n",
    "\n",
    "Here's my formulation of how *top spin* works. Starting withh a source string, in this case `topspin`, the poem contains successive lines that contain a substring of the source string, either ending with the letter in the middle or starting with the letter in the middle. The particular substring shown starts at an index that increases until it reaches the end of the string, then decreases until it reaches the beginning of the string, and then repeats.\n",
    "\n",
    "So how to implement this in python?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First, we'll assign our source string to a variable `s`. (Keeping the variable name short because we'll be using it a lot.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "s = \"topspin\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To find the index halfway through the string, divide the length of `s` by two:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "h = int(len(s) / 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "h"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Slicing up to this index gives us the first half of the string:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'top'"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s[:h]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And from this index to the end gives us the second half of the string:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'pin'"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s[-h:]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "So far so good."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Generating triangles\n",
    "\n",
    "In order to create the repeating pattern of substrings, we need to generate a list of indices that goes up to the end of the string and then back to the beginning. Ideally, we'd end up with something like this list:\n",
    "\n",
    "    [0, 1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]\n",
    "    \n",
    "... which goes from zero up to the last index of the source string (in this case, `6`) and then back down, stopping short before zero so the entire sequence can be repeated. We'll call this a *triangle range*, since if you visualize it, it looks like a sequence of triangles:\n",
    "\n",
    "        *       *\n",
    "       * *     * *\n",
    "      *   *   *   *\n",
    "     *     * *     *\n",
    "    *       *       * (etc.)\n",
    "\n",
    "The `range()` function in Python can produce the ascending part of this list:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "5\n",
      "6\n"
     ]
    }
   ],
   "source": [
    "for i in range(len(s)):\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To go back down, you can use the `reversed()` function on the result of `range()`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6\n",
      "5\n",
      "4\n",
      "3\n",
      "2\n",
      "1\n",
      "0\n"
     ]
    }
   ],
   "source": [
    "for i in reversed(range(len(s))):\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If the `range()` and `reversed()` functions returned *lists*, then we could just concatenate them together to get the up-and-down range we want. They're not lists, however; they're [iterable objects](https://treyhunner.com/2018/02/python-range-is-not-an-iterator/) that work as the thing being looped over in a `for` loop. The cleanest way to concatenate these is with the `chain` function from `itertools`, which chains together iterable objects (whether lists, generators, sequences, etc.):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "from itertools import chain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n",
      "2\n",
      "3\n",
      "a\n",
      "b\n",
      "c\n",
      "d\n"
     ]
    }
   ],
   "source": [
    "a = range(4)\n",
    "b = [\"a\", \"b\", \"c\", \"d\"]\n",
    "for item in chain(a, b):\n",
    "    print(item)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To create our up-and-down range, then, should be as easy as:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "5\n",
      "6\n",
      "6\n",
      "5\n",
      "4\n",
      "3\n",
      "2\n",
      "1\n",
      "0\n"
     ]
    }
   ],
   "source": [
    "for item in chain(range(len(s)), reversed(range(len(s)))):\n",
    "    print(item)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "That's not quite right, since we're repeating both the highest index and the lowest index. By adjusting the start and end parameters of the `range()` function, we can work around this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "5\n",
      "6\n",
      "5\n",
      "4\n",
      "3\n",
      "2\n",
      "1\n"
     ]
    }
   ],
   "source": [
    "for i in chain(range(len(s)-1), reversed(range(1, len(s)))):\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the following cell, I define a function that returns the chained iterables to create a triangle range with a given upper limit. We'll use this in the rest of the notebook:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 1, 2, 3, 2, 1]"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def trirange(n):\n",
    "    return chain(range(n-1), reversed(range(1, n)))\n",
    "list(trirange(4))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Approximating *top spin*\n",
    "\n",
    "Now that we can work up and down the range, we can start making things that are vaguely *top spin*-like. In this first example, I simply print out the letter at the corresponding index from a triangle range going up to the length of the string:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "t\n",
      "o\n",
      "p\n",
      "s\n",
      "p\n",
      "i\n",
      "n\n",
      "i\n",
      "p\n",
      "s\n",
      "p\n",
      "o\n"
     ]
    }
   ],
   "source": [
    "for i in trirange(len(s)):\n",
    "    print(s[i])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The multiplication operator `*` works on strings as well as numbers. When you use it with a string *t* on the left and a number *n* on the right, it produces a new string that has *n* copes of *t* in a row:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'xxxxxxxxxx'"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"x\" * 10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'howdyhowdyhowdyhowdyhowdyhowdyhowdyhowdyhowdyhowdyhowdyhowdyhowdyhowdyhowdyhowdyhowdyhowdyhowdyhowdy'"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"howdy\" * 20"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Taking advantage of this, we can produce a variation on *top spin* that has each letter at its index on subsequent lines, following a triangle range:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "t\n",
      " o\n",
      "  p\n",
      "   s\n",
      "    p\n",
      "     i\n",
      "      n\n",
      "     i\n",
      "    p\n",
      "   s\n",
      "  p\n",
      " o\n"
     ]
    }
   ],
   "source": [
    "for i in trirange(len(s)):\n",
    "    print((\" \" * i) + s[i])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Using an outer `for` loop to repeat this several times:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "t\n",
      " o\n",
      "  p\n",
      "   s\n",
      "    p\n",
      "     i\n",
      "      n\n",
      "     i\n",
      "    p\n",
      "   s\n",
      "  p\n",
      " o\n",
      "t\n",
      " o\n",
      "  p\n",
      "   s\n",
      "    p\n",
      "     i\n",
      "      n\n",
      "     i\n",
      "    p\n",
      "   s\n",
      "  p\n",
      " o\n",
      "t\n",
      " o\n",
      "  p\n",
      "   s\n",
      "    p\n",
      "     i\n",
      "      n\n",
      "     i\n",
      "    p\n",
      "   s\n",
      "  p\n",
      " o\n"
     ]
    }
   ],
   "source": [
    "for count in range(3):\n",
    "    for i in trirange(len(s)):\n",
    "        print((\" \" * i) + s[i])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We're nearly there! Now all we need is to write code that follows the rules we originally set out: following a triangle range, if the index is before the middle of the string, display the substring up to the middle (plus the middle character); otherwise, display the substring from the middle up to the end (inclusive). Here's code that implements that. (Remember that we defined `h` above to be the middle index of the string."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tops\n",
      " ops\n",
      "  ps\n",
      "   s\n",
      "   sp\n",
      "   spi\n",
      "   spin\n",
      "   spi\n",
      "   sp\n",
      "   s\n",
      "  ps\n",
      " ops\n"
     ]
    }
   ],
   "source": [
    "for i in trirange(len(s)):\n",
    "    if i < h:\n",
    "        print(s[i:h+1].rjust(h+1)) # +1 to include the middle character\n",
    "    else:\n",
    "        print((\" \" * h) + s[h:i+1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note the use of [`.rjust()`](https://docs.python.org/3/library/stdtypes.html?highlight=rjust#str.rjust) to justify the string to the right, given a particular length.\n",
    "\n",
    "## Generalizing *top spin*\n",
    "\n",
    "Just to make things cleaner and to make it easier to experiment with different inputs and outputs, I define a function below to create one \"spin\" of *top spin*:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "def spin(s):\n",
    "    h = int(len(s) / 2)\n",
    "    out = []\n",
    "    for i in trirange(len(s)):\n",
    "        if i < h:\n",
    "            out.append(s[i:h+1].rjust(h+1)) # +1 to include the middle character\n",
    "        else:\n",
    "            out.append((\" \" * h) + s[h:i+1])\n",
    "    return \"\\n\".join(out)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we can \"spin\" multiple times:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tops\n",
      " ops\n",
      "  ps\n",
      "   s\n",
      "   sp\n",
      "   spi\n",
      "   spin\n",
      "   spi\n",
      "   sp\n",
      "   s\n",
      "  ps\n",
      " ops\n",
      "tops\n",
      " ops\n",
      "  ps\n",
      "   s\n",
      "   sp\n",
      "   spi\n",
      "   spin\n",
      "   spi\n",
      "   sp\n",
      "   s\n",
      "  ps\n",
      " ops\n",
      "tops\n",
      " ops\n",
      "  ps\n",
      "   s\n",
      "   sp\n",
      "   spi\n",
      "   spin\n",
      "   spi\n",
      "   sp\n",
      "   s\n",
      "  ps\n",
      " ops\n",
      "tops\n",
      " ops\n",
      "  ps\n",
      "   s\n",
      "   sp\n",
      "   spi\n",
      "   spin\n",
      "   spi\n",
      "   sp\n",
      "   s\n",
      "  ps\n",
      " ops\n"
     ]
    }
   ],
   "source": [
    "for i in range(4):\n",
    "    print(spin(\"topspin\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And spin arbitrary strings:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "allisonp\n",
      " llisonp\n",
      "  lisonp\n",
      "   isonp\n",
      "    sonp\n",
      "     onp\n",
      "      np\n",
      "       p\n",
      "       pa\n",
      "       par\n",
      "       parr\n",
      "       parri\n",
      "       parris\n",
      "       parrish\n",
      "       parris\n",
      "       parri\n",
      "       parr\n",
      "       par\n",
      "       pa\n",
      "       p\n",
      "      np\n",
      "     onp\n",
      "    sonp\n",
      "   isonp\n",
      "  lisonp\n",
      " llisonp\n",
      "allisonp\n",
      " llisonp\n",
      "  lisonp\n",
      "   isonp\n",
      "    sonp\n",
      "     onp\n",
      "      np\n",
      "       p\n",
      "       pa\n",
      "       par\n",
      "       parr\n",
      "       parri\n",
      "       parris\n",
      "       parrish\n",
      "       parris\n",
      "       parri\n",
      "       parr\n",
      "       par\n",
      "       pa\n",
      "       p\n",
      "      np\n",
      "     onp\n",
      "    sonp\n",
      "   isonp\n",
      "  lisonp\n",
      " llisonp\n"
     ]
    }
   ],
   "source": [
    "for i in range(2):\n",
    "    print(spin(\"allisonparrish\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Experimental *top spin*s\n",
    "\n",
    "Here are a few variations on *top spin* for you to work through and play with.\n",
    "\n",
    "First off, a version that prints the negative space of the triangle range:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "def negativespace(s):\n",
    "    out = []\n",
    "    for i in trirange(len(s)):\n",
    "        missed = s[:i] + \" \" + s[i+1:]\n",
    "        out.append(missed)\n",
    "    return \"\\n\".join(out)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " lphabet\n",
      "a phabet\n",
      "al habet\n",
      "alp abet\n",
      "alph bet\n",
      "alpha et\n",
      "alphab t\n",
      "alphabe \n",
      "alphab t\n",
      "alpha et\n",
      "alph bet\n",
      "alp abet\n",
      "al habet\n",
      "a phabet\n",
      " lphabet\n",
      "a phabet\n",
      "al habet\n",
      "alp abet\n",
      "alph bet\n",
      "alpha et\n",
      "alphab t\n",
      "alphabe \n",
      "alphab t\n",
      "alpha et\n",
      "alph bet\n",
      "alp abet\n",
      "al habet\n",
      "a phabet\n"
     ]
    }
   ],
   "source": [
    "for i in range(2):\n",
    "    print(negativespace(\"alphabet\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, a version that prints a zigzag \"stripe\" from the string:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "def zigzag(s, chunklen=2):\n",
    "    out = []\n",
    "    for i in trirange(len(s)-(chunklen-1)):\n",
    "        out.append(\" \" * i + s[i:i+chunklen])\n",
    "    return \"\\n\".join(out)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "zig\n",
      " igz\n",
      "  gza\n",
      "   zag\n",
      "  gza\n",
      " igz\n",
      "zig\n",
      " igz\n",
      "  gza\n",
      "   zag\n",
      "  gza\n",
      " igz\n",
      "zig\n",
      " igz\n",
      "  gza\n",
      "   zag\n",
      "  gza\n",
      " igz\n",
      "zig\n",
      " igz\n",
      "  gza\n",
      "   zag\n",
      "  gza\n",
      " igz\n"
     ]
    }
   ],
   "source": [
    "for i in range(4):\n",
    "    print(zigzag(\"zigzag\", 3))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And finally, a new range function that returns an range of indices that follow a sine wave (well, actually an inverted *cosine* wave) instead of a triangle, smoothly ramping up and back down:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "import math\n",
    "def sinerange(n, steps=10):\n",
    "    for i in range(steps):\n",
    "        theta = (math.tau / steps) * i\n",
    "        yield int(n/2 * (-1*math.cos(theta))) + int(n/2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The second parameter (`steps`) sets the \"smoothness\" of the wave:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 1, 1, 2, 3, 4, 5, 5, 7, 8, 9, 9, 9, 9, 9, 9, 8, 7, 5, 5, 4, 3, 2, 1, 1]"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(sinerange(10, 25))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here's the single-letter variant of *top spin* produced with this range function:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "t\n",
      "t\n",
      " o\n",
      "  p\n",
      "   s\n",
      "    p\n",
      "     i\n",
      "      n\n",
      "      n\n",
      "      n\n",
      "     i\n",
      "    p\n",
      "   s\n",
      "  p\n",
      " o\n",
      "t\n",
      "t\n",
      "t\n",
      " o\n",
      "  p\n",
      "   s\n",
      "    p\n",
      "     i\n",
      "      n\n",
      "      n\n",
      "      n\n",
      "     i\n",
      "    p\n",
      "   s\n",
      "  p\n",
      " o\n",
      "t\n"
     ]
    }
   ],
   "source": [
    "for i in range(2):\n",
    "    for i in sinerange(len(s), steps=16):\n",
    "        print(\" \" * i + s[i])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Combining the zigzag stripe with the sine range:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "def sinezigzag(s, chunklen=2, steps=16):\n",
    "    out = []\n",
    "    for i in sinerange(len(s)-(chunklen-1), steps):\n",
    "        out.append(\" \" * i + s[i:i+chunklen])\n",
    "    return \"\\n\".join(out)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "trigo\n",
      "trigo\n",
      " rigon\n",
      " rigon\n",
      "  igono\n",
      "   gonom\n",
      "    onome\n",
      "     nomet\n",
      "      ometr\n",
      "       metry\n",
      "       metry\n",
      "        etry!\n",
      "        etry!\n",
      "        etry!\n",
      "       metry\n",
      "       metry\n",
      "      ometr\n",
      "     nomet\n",
      "    onome\n",
      "   gonom\n",
      "  igono\n",
      " rigon\n",
      " rigon\n",
      "trigo\n",
      "trigo\n",
      "trigo\n",
      " rigon\n",
      " rigon\n",
      "  igono\n",
      "   gonom\n",
      "    onome\n",
      "     nomet\n",
      "      ometr\n",
      "       metry\n",
      "       metry\n",
      "        etry!\n",
      "        etry!\n",
      "        etry!\n",
      "       metry\n",
      "       metry\n",
      "      ometr\n",
      "     nomet\n",
      "    onome\n",
      "   gonom\n",
      "  igono\n",
      " rigon\n",
      " rigon\n",
      "trigo\n",
      "trigo\n",
      "trigo\n",
      " rigon\n",
      " rigon\n",
      "  igono\n",
      "   gonom\n",
      "    onome\n",
      "     nomet\n",
      "      ometr\n",
      "       metry\n",
      "       metry\n",
      "        etry!\n",
      "        etry!\n",
      "        etry!\n",
      "       metry\n",
      "       metry\n",
      "      ometr\n",
      "     nomet\n",
      "    onome\n",
      "   gonom\n",
      "  igono\n",
      " rigon\n",
      " rigon\n",
      "trigo\n"
     ]
    }
   ],
   "source": [
    "for i in range(3):\n",
    "    print(sinezigzag(\"trigonometry!\", 5, 24))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
